using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.Collections.Generic;
using QiAdmin.Core;
using QiAdmin.Core.Services.Log;
using QiAdmin.Core.Services.Token;
using QiAdmin.Entity;
using QiAdmin.Model.Dtos;
using QiAdmin.Model.Dtos.Input;
using QiAdmin.Model.Dtos.Output;
using QiAdmin.Model.System.Models;
using QiAdmin.Repository.Repository;
using QiAdmin.Service.IService;
using ICacheService = QiAdmin.Core.Services.Cache.ICacheService;

namespace QiAdmin.Service.Service
{
    /// <summary>
    /// TSysMenu Services
    /// </summary>
    public class TSysMenuService : BaseService<TSysMenu, TSysMenu_IN, TSysMenu_OUT>, ITSysMenuService
    {
        readonly TSysMenuRepository _tSysMenuRepository;
        readonly TSysRoleMenuRepository _tSysRoleMenuRepository;
        public TSysMenuService(ILogService logService,
            ITokenService tokenService, ICacheService cacheService, IHttpContextAccessor httpContextAccessor, TSysMenuRepository tSysMenuRepository, TSysRoleMenuRepository tSysRoleMenuRepository) : base(logService, tokenService, cacheService, httpContextAccessor.HttpContext)
        {
            _tSysMenuRepository = tSysMenuRepository;
            _tSysRoleMenuRepository = tSysRoleMenuRepository;
        }

        #region 增删改查-自动生成

        /// <summary>
        /// 创建默认条件
        /// </summary>
        /// <returns></returns>
        public Expressionable<TSysMenu> CreateExp()
        {
            var exp = Expressionable.Create<TSysMenu>();
            return exp;
        }

        /// <summary>
        /// 新增单条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult Add(TSysMenu_IN input)
        {
            var model = input.Adapt<TSysMenu>();
            int Id = _tSysMenuRepository.InsertReturnIdentity(model);
            //同步到超级管理员
            _tSysRoleMenuRepository.Insert(new TSysRoleMenu
            {
                RoleId = App.StaticData.SystemRole,
                MenuId = Id
            });
            return CommonResult.Convert(Id > 0);
        }

        /// <summary>
        /// 新增多条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult AddRange(List<TSysMenu_IN> input)
        {
            var list = input.Adapt<List<TSysMenu>>();
            var result = _tSysMenuRepository.InsertRange(list);
            return CommonResult.Convert(result);
        }

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult Edit(TSysMenu_IN input)
        {
            var exp = CreateExp();
            exp.And(t => t.Id == input.Id);
            var model = input.Adapt<TSysMenu>();
            var result = _tSysMenuRepository.UpdateAndIgnore(model, exp.ToExpression());
            return CommonResult.Convert(result);
        }

        /// <summary>
        /// 获取单条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult<TSysMenu_OUT> Get(TSysMenu_IN input)
        {
            var exp = CreateExp();
            exp.And(t => t.Id == input.Id);

            var result = _tSysMenuRepository.GetFirst(exp.ToExpression()).Adapt<TSysMenu_OUT>();
            return new CommonResult<TSysMenu_OUT>(result);
        }

        /// <summary>
        /// 分页获取
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult<PageOutput<TSysMenu_OUT>> GetPageList(TSysMenu_IN input)
        {
            var exp = CreateExp();

            exp.AndIF(input.StartQueryTime != DateTime.MinValue, t => t.SysCreateTime >= input.StartQueryTime.Date);
            exp.AndIF(input.EndQueryTime != DateTime.MinValue, t => t.SysCreateTime < input.EndQueryTime.Date.AddDays(1));

            PageOutput<TSysMenu_OUT> pageOutput = new PageOutput<TSysMenu_OUT>();
            PageModel pageModel = new() { PageIndex = input.PageIndex, PageSize = input.PageSize };
            pageOutput.Data = _tSysMenuRepository.GetPageList(exp.ToExpression(), pageModel).Adapt<List<TSysMenu_OUT>>();
            pageOutput.DataCount = pageModel.TotalCount;

            return new CommonResult<PageOutput<TSysMenu_OUT>>(pageOutput);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult Remove(TSysMenu_IN input)
        {
            var exp = CreateExp();
            exp.And(t => t.Id == input.Id);

            var result = _tSysMenuRepository.Delete(exp.ToExpression());
            return CommonResult.Convert(result);
        }

        /// <summary>
        /// 删除多条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult RemoveRange(List<TSysMenu_IN> input)
        {
            var exp = CreateExp();
            exp.And(t => input.Select(s => s.Id).Contains(t.Id));

            var result = _tSysMenuRepository.Delete(exp.ToExpression());
            return CommonResult.Convert(result);
        }

        #endregion


        /// <summary>
        /// 获取菜单数据(树形结构)
        /// </summary>
        /// <returns></returns>
        public CommonResult<List<TreeMenu>> GetMenus(TSysMenu_IN input)
        {
            var exp = CreateExp();
            exp.AndIF(!string.IsNullOrEmpty(input.Title), t => t.Title == input.Title);
            var tree = _tSysMenuRepository.Context.Queryable<TSysMenu>().Where(exp.ToExpression()).Select(t => new TreeMenu
            {
                ParentId = t.ParentId,
                Id = t.Id,
                Component = t.Component,
                Title = t.Title,
                Name = t.Name,
                Sort = t.Sort,
                Icon = t.Icon,
                IsHide = t.IsHide,
                Path = t.Path,
                Type = t.Type,
                ApiTag = t.ApiTag,
                Permission = t.Permission,
                Url = t.Url,
            }).OrderBy(s => s.Sort).ToTree(s => s.children, s => s.ParentId, 0, s => s.Id);
            return new CommonResult<List<TreeMenu>>(tree);
        }

        /// <summary>
        /// 给页面添加按钮(控制权限)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult AddPageButtons(TSysMenu_IN input)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>
            {
                { "Add", "新增" },
                { "Edit", "编辑" },
                { "Delete", "删除" }
            };
            var parent = _tSysMenuRepository.GetById(input.Id);
            var btns = _tSysMenuRepository.GetList(t => t.ParentId == input.Id && t.Type == "Button");
            foreach (var item in dic)
            {
                if (!btns.Exists(t => t.Name == item.Key))
                {
                    TSysMenu sysMenu = new TSysMenu
                    {
                        ParentId = parent.Id,
                        Title = item.Value,
                        Name = item.Key,
                        Path = parent.Path,
                        Component = parent.Component,
                        Type = "Button",
                        ApiTag = input.ApiTag,
                        Permission = string.Join(",", App.StaticData.PermissionTypes.Where(s => s == item.Key)) + ",",
                    };
                    _tSysMenuRepository.Insert(sysMenu);
                }
            }
            return CommonResult.Success;
        }

        public CommonResult RemoveMenu(TSysMenu_IN input)
        {
            ITenant tenant = _tSysMenuRepository.AsTenant();
            try
            {
                tenant.BeginTran();
                //递归获取菜单数据
                var menus = _tSysMenuRepository.GetRecursiveMenu(input.Id);
                //删除菜单数据
                _tSysMenuRepository.DeleteByIds(menus.Select(s => (dynamic)s.Id).ToArray());
                //删除分配到角色的菜单数据
                _tSysRoleMenuRepository.Delete(t => menus.Select(s => s.Id).Contains(t.MenuId));
                tenant.CommitTran();
                return CommonResult.Success;
            }
            catch
            {
                tenant.RollbackTran();
                return CommonResult.Error;
            }

        }
    }
}
